Objective-C Runtime

Objective-C Runtime是提供Objective-C语言动态特性的运行时的库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
/* Types */
#if !OBJC_TYPES_DEFINED
// 类方法
typedef struct objc_method *Method;
// 实例变量
typedef struct objc_ivar *Ivar;
// 分类
typedef struct objc_category *Category;
// 对象声明的属性
typedef struct objc_property *objc_property_t;
// objc_class结构体
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE; // 父类
const char *name OBJC2_UNAVAILABLE; // 类名
long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0
long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识
long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表
struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表
struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表
#endif
} OBJC2_UNAVAILABLE;
#endif
#ifdef __OBJC__
@class Protocol;
#else
typedef struct objc_object Protocol;
#endif
// 定义方法
struct objc_method_description {
SEL name; // 方法的名称
char *types; // 方法的参数类型
};
// 定义属性
typedef struct {
const char *name; // 属性名称
const char *value; // 属性值
} objc_property_attribute_t;
/* 实例方法 */
// 返回指定对象的一个副本
OBJC_EXPORT id object_copy(id obj, size_t size);
// 释放指定对象内存 返回nil
OBJC_EXPORT id object_dispose(id obj);
// 返回对象的类
OBJC_EXPORT Class object_getClass(id obj);
// 设置对象的类
OBJC_EXPORT Class object_setClass(id obj, Class cls);
// 是否是类对象
OBJC_EXPORT BOOL object_isClass(id obj);
// 返回给定对象的类名
OBJC_EXPORT const char *object_getClassName(id obj);
// 返回指向给定对象分配的任何额外字节的指针
OBJC_EXPORT void *object_getIndexedIvars(id obj);
// 返回对象中实例变量的值
OBJC_EXPORT id object_getIvar(id obj, Ivar ivar);
// 设置对象中实例变量的值
OBJC_EXPORT void object_setIvar(id obj, Ivar ivar, id value);
// 在对象中设置实例变量的值 iOS 10 AVAILABLE
OBJC_EXPORT void object_setIvarWithStrongDefault(id obj, Ivar ivar, id value);
// 修改类实例的实例变量的值
OBJC_EXPORT Ivar object_setInstanceVariable(id obj, const char *name, void *value);
// 更改一个实例类中实例变量的值 iOS 10 AVAILABLE
OBJC_EXPORT Ivar object_setInstanceVariableWithStrongDefault(id obj, const char *name, void *value);
// 返回对象实例变量的值
OBJC_EXPORT Ivar object_getInstanceVariable(id obj, const char *name, void **outValue);
/* 类方法 */
// 返回指定的类
OBJC_EXPORT Class objc_getClass(const char *name);
// 返回指定的元类
OBJC_EXPORT Class objc_getMetaClass(const char *name);
// 返回指定的类
OBJC_EXPORT Class objc_lookUpClass(const char *name);
// 返回指定的类
OBJC_EXPORT Class objc_getRequiredClass(const char *name);
// 返回已注册的类定义的列表
OBJC_EXPORT int objc_getClassList(Class *buffer, int bufferCount);
// 创建并返回一个指向所有已注册类的指针列表
OBJC_EXPORT Class *objc_copyClassList(unsigned int *outCount);
// 返回类的类名
OBJC_EXPORT const char *class_getName(Class cls);
// 是否是元类
OBJC_EXPORT BOOL class_isMetaClass(Class cls);
// 返回类的父类
OBJC_EXPORT Class class_getSuperclass(Class cls);
// 给类指定一个父类
OBJC_EXPORT Class class_setSuperclass(Class cls, Class newSuper);
// 返回类版本号
OBJC_EXPORT int class_getVersion(Class cls);
// 设置类版本号
OBJC_EXPORT void class_setVersion(Class cls, int version);
// 返回实例类的大小
OBJC_EXPORT size_t class_getInstanceSize(Class cls);
// 返回类中指定名称实例成员变量的信息
OBJC_EXPORT Ivar class_getInstanceVariable(Class cls, const char *name);
// 返回类成员变量的信息
OBJC_EXPORT Ivar class_getClassVariable(Class cls, const char *name);
// 返回整个成员变量列表
OBJC_EXPORT Ivar *class_copyIvarList(Class cls, unsigned int *outCount);
// 返回实例方法
OBJC_EXPORT Method class_getInstanceMethod(Class cls, SEL name);
// 返回类方法
OBJC_EXPORT Method class_getClassMethod(Class cls, SEL name);
// 返回类方法实现的指针
OBJC_EXPORT IMP class_getMethodImplementation(Class cls, SEL name);
// 返回类方法实现的指针
OBJC_EXPORT IMP class_getMethodImplementation_stret(Class cls, SEL name);
// 类实例是否响应指定的selector
OBJC_EXPORT BOOL class_respondsToSelector(Class cls, SEL sel);
// 返回所有方法的数组
OBJC_EXPORT Method *class_copyMethodList(Class cls, unsigned int *outCount);
// 返回类是否实现指定的协议
OBJC_EXPORT BOOL class_conformsToProtocol(Class cls, Protocol *protocol);
// 返回类实现的协议列表
OBJC_EXPORT Protocol * __unsafe_unretained
*class_copyProtocolList(Class cls, unsigned int *outCount);
// 返回指定的属性
OBJC_EXPORT objc_property_t class_getProperty(Class cls, const char *name);
// 返回属性列表
OBJC_EXPORT objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount);
// 返回指定变量布局
OBJC_EXPORT const uint8_t *class_getIvarLayout(Class cls);
// 返回指定弱引用的变量布局
OBJC_EXPORT const uint8_t *class_getWeakIvarLayout(Class cls);
// 添加方法 如果返回YES则添加成功
OBJC_EXPORT BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);
// 替代方法的实现
OBJC_EXPORT IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types);
// 添加变量
OBJC_EXPORT BOOL class_addIvar(Class cls, const char *name, size_t size,uint8_t alignment, const char *types);
// 添加协议
OBJC_EXPORT BOOL class_addProtocol(Class cls, Protocol *protocol);
// 添加属性
OBJC_EXPORT BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount);
// 替换属性
OBJC_EXPORT void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount);
// 设置变量布局
OBJC_EXPORT void class_setIvarLayout(Class cls, const uint8_t *layout);
// 设置弱属性的变量布局
OBJC_EXPORT void class_setWeakIvarLayout(Class cls, const uint8_t *layout);
// 通过CoreFoundation's自由连接。不能自己调用此方法
OBJC_EXPORT Class objc_getFutureClass(const char *name);
// 创建类实例
OBJC_EXPORT id class_createInstance(Class cls, size_t extraBytes);
// 在指定位置创建类实例
OBJC_EXPORT id objc_constructInstance(Class cls, void *bytes);
// 销毁类实例
OBJC_EXPORT void *objc_destructInstance(id obj);
// 创建新的类
OBJC_EXPORT Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);
// 注册创建的类
OBJC_EXPORT void objc_registerClassPair(Class cls);
// 用于KVO观察者模式。 不能自己调用此方法
OBJC_EXPORT Class objc_duplicateClass(Class original, const char *name, size_t extraBytes);
// 销毁一个类及其相关联的类
OBJC_EXPORT void objc_disposeClassPair(Class cls);
// 返回方法的名称
OBJC_EXPORT SEL method_getName(Method m);
// 返回一个方法指针
OBJC_EXPORT IMP method_getImplementation(Method m);
// 返回描述方法的字符串
OBJC_EXPORT const char *method_getTypeEncoding(Method m);
// 返回方法接收参数的个数
OBJC_EXPORT unsigned int method_getNumberOfArguments(Method m);
// 返回描述方法返回类型的字符串
OBJC_EXPORT char *method_copyReturnType(Method m);
// 返回描述方法单个参数类型的字符串
OBJC_EXPORT char *method_copyArgumentType(Method m, unsigned int index);
// 返回一个描述方法返回类型
OBJC_EXPORT void method_getReturnType(Method m, char *dst, size_t dst_len);
// 返回描述方法单个参数类型
OBJC_EXPORT void method_getArgumentType(Method m, unsigned int index, char *dst, size_t dst_len);
// 返回指定方法的结构描述
OBJC_EXPORT struct objc_method_description *method_getDescription(Method m);
// 设置方法的指针地址
OBJC_EXPORT IMP method_setImplementation(Method m, IMP imp);
/**
* 交换两个方法指针地址
* @note 交换原理如下:
* \code
* IMP imp1 = method_getImplementation(m1);
* IMP imp2 = method_getImplementation(m2);
* method_setImplementation(m1, imp2);
* method_setImplementation(m2, imp1);
* \endcode
*/
OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2);
// 返回实例变量的名称
OBJC_EXPORT const char *ivar_getName(Ivar v);
// 返回实例变量类型的字符串
OBJC_EXPORT const char *ivar_getTypeEncoding(Ivar v);
// 返回实例变量的偏移量
OBJC_EXPORT ptrdiff_t ivar_getOffset(Ivar v);
// 返回
OBJC_EXPORT const char *property_getName(objc_property_t property);
// 返回属性的属性字符串
OBJC_EXPORT const char *property_getAttributes(objc_property_t property);
// 返回属性的属性数组
OBJC_EXPORT objc_property_attribute_t *property_copyAttributeList(objc_property_t property, unsigned int *outCount);
// 返回指定属性名称的属性的值
OBJC_EXPORT char *property_copyAttributeValue(objc_property_t property, const char *attributeName);
// 返回协议的名称
OBJC_EXPORT Protocol *objc_getProtocol(const char *name);
// 返回runtime已知的所有协议的数组
OBJC_EXPORT Protocol * __unsafe_unretained *objc_copyProtocolList(unsigned int *outCount);
// 判断一个协议是否遵循了另一个协议
OBJC_EXPORT BOOL protocol_conformsToProtocol(Protocol *proto, Protocol *other);
// 判断两个协议是否相等
OBJC_EXPORT BOOL protocol_isEqual(Protocol *proto, Protocol *other);
// 返回协议的名称
OBJC_EXPORT const char *protocol_getName(Protocol *p);
// 返回执行协议指定方法结构的描述
OBJC_EXPORT struct objc_method_description protocol_getMethodDescription(Protocol *p, SEL aSel, BOOL isRequiredMethod, BOOL isInstanceMethod);
// 返回满足指定协议方法描述的数组
OBJC_EXPORT struct objc_method_description *protocol_copyMethodDescriptionList(Protocol *p, BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *outCount);
// 返回指定协议的属性
OBJC_EXPORT objc_property_t protocol_getProperty(Protocol *proto, const char *name, BOOL isRequiredProperty, BOOL isInstanceProperty);
/**
* 返回声明协议所需要的属性的数组.
* @note Identical to
* \code
* protocol_copyPropertyList2(proto, outCount, YES, YES);
* \endcode
*/
OBJC_EXPORT objc_property_t *protocol_copyPropertyList(Protocol *proto, unsigned int *outCount);
OBJC_EXPORT objc_property_t *protocol_copyPropertyList2(Protocol *proto, unsigned int *outCount, BOOL isRequiredProperty, BOOL isInstanceProperty)
OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0);
// 返回协议所采用的协议的数组
OBJC_EXPORT Protocol * __unsafe_unretained *protocol_copyProtocolList(Protocol *proto, unsigned int *outCount);
// 创建一个新的协议,添加到objc_registerProtocol方法中
OBJC_EXPORT Protocol *objc_allocateProtocol(const char *name);
// 注册新协议
OBJC_EXPORT void objc_registerProtocol(Protocol *proto);
// 添加一个方法到协议中,此协议必须正在建设中
OBJC_EXPORT void protocol_addMethodDescription(Protocol *proto, SEL name, const char *types, BOOL isRequiredMethod, BOOL isInstanceMethod);
// 把已经建设的协议添加到正在建设的协议中去
OBJC_EXPORT void protocol_addProtocol(Protocol *proto, Protocol *addition);
// 添加一个属性到协议中去,此协议必须正在建设中
OBJC_EXPORT void protocol_addProperty(Protocol *proto, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount, BOOL isRequiredProperty, BOOL isInstanceProperty);
// 返回所有加载在Objective-C框架和动态库上的名称
OBJC_EXPORT const char **objc_copyImageNames(unsigned int *outCount);
// 返回一个来自类动态库的名称
OBJC_EXPORT const char *class_getImageName(Class cls);
// 返回库中所有类的名称
OBJC_EXPORT const char **objc_copyClassNamesForImage(const char *image,unsigned int *outCount);
// 返回指定sel的方法的名称
OBJC_EXPORT const char *sel_getName(SEL sel);
// 注册一个Objective-C运行时系统的方法名称
OBJC_EXPORT SEL sel_getUid(const char *str);
// 注册一个sel方法,并映方法名称到sel中并返回sel值
OBJC_EXPORT SEL sel_registerName(const char *str);
// 判断两个sel是否相同
OBJC_EXPORT BOOL sel_isEqual(SEL lhs, SEL rhs);
// 当发现突变的foreach迭代过程中时插入编译器
OBJC_EXPORT void objc_enumerationMutation(id obj);
// 设置当前突变的处理程序
OBJC_EXPORT void objc_setEnumerationMutationHandler(void (*handler)(id));
// 设置函数调用objc_msgForward
OBJC_EXPORT void objc_setForwardHandler(void *fwd, void *fwd_stret);
// 创建一个当调用此方法时调用指定块的函数指针
OBJC_EXPORT IMP imp_implementationWithBlock(id block);
// 返回一个使用imp_implementationWithBlock创建的与块相关的函数指针
OBJC_EXPORT id imp_getBlock(IMP anImp);
// 移除与函数指针相关联的块
OBJC_EXPORT BOOL imp_removeBlock(IMP anImp);
// 加载弱指针引用的对象并返回它
OBJC_EXPORT id objc_loadWeak(id *location);
// 存储_weak变量的新值
OBJC_EXPORT id objc_storeWeak(id *location, id obj);
// 设置关联
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
// 获取关联值
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key);
// 移除关联对象
OBJC_EXPORT void objc_removeAssociatedObjects(id object);
// 发送一个具有简单返回值的消息到一个实例类上
OBJC_EXPORT void objc_msgSend(void /* id self, SEL op, ... */ );
// 发送一个具有结构返回值的消息到一个实例类上
OBJC_EXPORT void objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ );
// 发送一个具有返回数据结构值的消息到一个实例类上
OBJC_EXPORT void objc_msgSend_stret(void /* id self, SEL op, ... */ );
// 发送一个具有返回数据结构值的消息到一个实例父类上
OBJC_EXPORT void objc_msgSendSuper_stret(void /* struct objc_super *super, SEL op, ... */ );
// 发送一个具有返回浮点类型值的消息到一个实例类上
OBJC_EXPORT void objc_msgSend_fpret(void /* id self, SEL op, ... */ );
OBJC_EXPORT void objc_msgSend_fp2ret(void /* id self, SEL op, ... */ );
// 调用指定方法的实现
OBJC_EXPORT void method_invoke(void /* id receiver, Method m, ... */ );
// 调用返回数据结构的指定方法的实现
OBJC_EXPORT void method_invoke_stret(void /* id receiver, Method m, ... */ );
// 关联策略
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
OBJC_ASSOCIATION_ASSIGN = 0, // 表示弱引用关联,非线程安全,通常是数据类型
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, // 表示强(strong)引用关联对象,非线程安全
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, // 表示关联对象copy,非线程安全
OBJC_ASSOCIATION_RETAIN = 01401, // 表示强(strong)引用关联对象,是线程安全的
OBJC_ASSOCIATION_COPY = 01403 // 表示关联对象copy,是线程安全的
};
// 编码类型
#define _C_ID '@' // 代表对象类型
#define _C_CLASS '#' // 代表类对象 (Class)
#define _C_SEL ':' // 代表方法selector (SEL)
#define _C_CHR 'c' // 代表char类型
#define _C_UCHR 'C' // 代表unsigned char类型
#define _C_SHT 's' // 代表short类型
#define _C_USHT 'S' // 代表unsigned short类型
#define _C_INT 'i' // 代表int类型
#define _C_UINT 'I' // 代表unsigned int类型
#define _C_LNG 'l' // 代表long类型,在64位处理器上也是按照32位处理
#define _C_ULNG 'L' // 代表unsigned long类型
#define _C_LNG_LNG 'q' // 代表long long类型
#define _C_ULNG_LNG 'Q' // 代表unsigned long long类型
#define _C_FLT 'f' // 代表float类型
#define _C_DBL 'd' // 代表double类型
#define _C_BFLD 'b' //
#define _C_BOOL 'B' // 代表C++中的bool或者C99中的_Bool
#define _C_VOID 'v' // 代表void类型
#define _C_UNDEF '?' // 代表未知类型
#define _C_PTR '^' // 代表指针类型
#define _C_CHARPTR '*' // 代表字符串类型 (char *)
#define _C_ATOM '%' //
#define _C_ARY_B '[' // 代表array
#define _C_ARY_E ']'
#define _C_UNION_B '(' // 代表UNION
#define _C_UNION_E ')'
#define _C_STRUCT_B '{' // 代表结构体
#define _C_STRUCT_E '}'
#define _C_VECTOR '!' // 代表矢量类型
#define _C_CONST 'r' // 代表常量类型

例子1 Runtime

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// 获取属性列表&&获取属性名称
unsigned int count;
objc_property_t *propertyList = class_copyPropertyList([self class], &count);
for (int i = 0; i < count ; i++) {
const char *propertyName = property_getName(propertyList[i]);
NSString *str = [NSString stringWithUTF8String:propertyName];
NSLog(@"property_getName==%@",str);
}
// 获取方法列表&&获取方法名称
Method *methodList = class_copyMethodList([self class], &count);
for (int i = 0; i < count; i++) {
Method method = methodList[i];
//获取方法的参数列表
int arguments = method_getNumberOfArguments(method);
NSLog(@"method_getNumberOfArguments===%d",arguments);
NSLog(@"method_getName===%@",NSStringFromSelector(method_getName(method)));
}
// 获取类成员变量列表&&获取成员变量名称
Ivar *ivarList = class_copyIvarList([self class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivarList[i];
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
NSLog(@"ivar_getName===%@",ivarName);
}
// 获取类协议列表&&获取协议名称
__unsafe_unretained Protocol **protocolList = class_copyProtocolList([self class], &count);
for (unsigned int i = 0; i < count; i++) {
Protocol *protocol = protocolList[i];
NSString *protocolStr = [NSString stringWithUTF8String:protocol_getName(protocol)];
NSLog(@"protocol_getName===%@",protocolStr);
}
// 是不是元类
BOOL isMetaClass = class_isMetaClass(self.class);
NSLog(@"ViewController is the meta class? %d", isMetaClass);
// 是不是类对象
ViewController *obj = [ViewController new];
BOOL isClass = object_isClass(obj);
NSLog(@"ViewController is the class? %d", isClass);
// 获取类名称
const char *name = class_getName(self.class);
NSLog(@"class_getName===%@",[NSString stringWithCString:name encoding:NSUTF8StringEncoding]);
// 设置关联&&获取关联
static char *key = "key";
objc_setAssociatedObject(self, &key, @"hello world", OBJC_ASSOCIATION_COPY_NONATOMIC);
NSString *associated = objc_getAssociatedObject(self, &key);
NSLog(@"objc_getAssociatedObject===%@",associated);
/*----------------------Method Swizzling------------------------*/
// 获取实例方法
Method originalMethod = class_getInstanceMethod([self class], @selector(original:));
Method exchangeMethod = class_getInstanceMethod([self class], @selector(exchange:));
// 获取方法指针
IMP exchangeImp = method_getImplementation(exchangeMethod);
IMP originalImp = method_getImplementation(originalMethod);
// 获取描述方法的参数类型
const char *originalType = method_getTypeEncoding(originalMethod);
const char *exchangeType = method_getTypeEncoding(exchangeMethod);
// 添加方法
BOOL didAddMethod = class_addMethod([self class],
@selector(original:),
exchangeImp,
exchangeType);
if (didAddMethod) {
// 替换方法
class_replaceMethod([self class],
@selector(exchange:),
originalImp,
originalType);
}else{
// Method Swizzling
method_exchangeImplementations(exchangeMethod, originalMethod);
}
/*----------------------Method Swizzling------------------------*/

例子2 Runtime message

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 初始化 [[MsgSend1 alloc] init];
MsgSend1 *msg = ((MsgSend1 * (*)(id,SEL))objc_msgSend)((id)[MsgSend1 class], @selector(alloc));
msg = ((MsgSend1 * (*)(id,SEL))objc_msgSend)((id)msg, @selector(init));
// 发送无参无返回值消息
((void (*)(id,SEL))objc_msgSend)((id)msg, @selector(noArgumentsAndNoReturnValue));
// 发送有参数无返回值得消息
((void (*)(id,SEL,NSString *))objc_msgSend)((id)msg, @selector(hasArguments:),@"带参数但是无返回值");
// 带返回值不带参数消息
NSString *retValue = ((NSString * (*)(id,SEL))objc_msgSend)((id)msg,@selector(noArgumentsButReturnValue));
NSLog(@"%@",retValue);
// 带参数带返回值消息
int returnValue = ((int (*)(id,SEL,NSString *,int))objc_msgSend)((id)msg,@selector(hasValue1:Value2:),@"参数",999);
NSLog(@"return value is %d",returnValue);
// 动态添加方法再调用 其中i代表返回类型int,@代表参数,:代表SEL
class_addMethod(msg.class, NSSelectorFromString(@"cStyleFunc"), (IMP)cStyleFunc,"i@:");
returnValue = ((int (*)(id,SEL,const void *,const void *))objc_msgSend)((id)msg,NSSelectorFromString(@"cStyleFunc"),"one","two");
NSLog(@"return value is %d",returnValue);
// 带返回浮点值的消息
//objc_msgSend
//float returnFloatValue = ((float (*)(id,SEL))objc_msgSend)((id)msg,@selector(returnFloatType));
//objc_msgSend_fpret
float returnFloatValue = ((float (*)(id,SEL))objc_msgSend_fpret)((id)msg,@selector(returnFloatType));
NSLog(@"return float is %f",returnFloatValue);
// 带结构体返回值的消息
//objc_msgSend_stret
CGRect frame = ((CGRect (*)(id,SEL))objc_msgSend_stret)((id)self,@selector(returnTypeIsStruct));
NSLog(@"return frame is %@",NSStringFromCGRect(frame));